package com.eonmind.user.service.impl;

import com.eonmind.common.contract.data.response.PageResponse;
import com.eonmind.common.contract.enums.user.UserNoticeStatus;
import com.eonmind.common.contract.exception.BusinessException;
import com.eonmind.common.provider.entity.user.NotificationType;
import com.eonmind.common.provider.entity.user.User;
import com.eonmind.common.provider.entity.user.UserNotification;
import com.eonmind.common.provider.entity.user.UserNotificationPreference;
import com.eonmind.user.contract.dto.UserInfoData;
import com.eonmind.user.converts.UserNoticeConvert;
import com.eonmind.user.dto.UserNoticeDto;
import com.eonmind.user.mapper.NotificationTypeMapper;
import com.eonmind.user.mapper.UserMapper;
import com.eonmind.user.mapper.UserNotificationMapper;
import com.eonmind.user.mapper.UserNotificationPreferenceMapper;
import com.eonmind.user.service.INoticeService;
import com.mongoplus.model.PageResult;
import jakarta.annotation.Resource;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.ObjectUtils;
import org.apache.commons.lang3.StringUtils;
import org.springframework.scheduling.annotation.Async;
import org.springframework.stereotype.Service;

import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.function.Function;
import java.util.stream.Collectors;

import static com.eonmind.common.contract.enums.ErrorCode.PARAMS_ERROR;

/**
 * 通知服务实现类
 *
 * @author Xujie
 * @since 2025/6/1 11:14
 **/
@Slf4j
@Service
public class NoticeService implements INoticeService {
    @Resource
    private NotificationTypeMapper notificationTypeMapper;
    @Resource
    private UserNotificationPreferenceMapper userNotificationPreferenceMapper;
    @Resource
    private UserMapper userMapper;

    @Resource
    private UserNotificationMapper userNotificationMapper;

    @Override
    public List<UserNoticeDto.UserNoticePreferenceResponse> userNoticePreference(UserInfoData userInfoData) {
        Long userId = userInfoData.getId();
        List<UserNotificationPreference> userNotificationPreferenceList = userNotificationPreferenceMapper.selectByUserId(userId);
        List<Long> noticeTypeIds = userNotificationPreferenceList.stream()
                .map(UserNotificationPreference::getNoticeTypeId)
                .toList();
        List<NotificationType> notificationTypeList = notificationTypeMapper.selectByIds(noticeTypeIds);
        Map<Long, NotificationType> noticeTypeMap = notificationTypeList.stream()
                .collect(Collectors.toMap(NotificationType::getId, Function.identity()));
        List<UserNoticeDto.UserNoticePreferenceResponse> userNoticePreferenceList = userNotificationPreferenceList.stream()
                .map(userNotificationPreference -> {
                    UserNoticeDto.UserNoticePreferenceResponse userNoticePreferenceResponse = new UserNoticeDto.UserNoticePreferenceResponse();
                    userNoticePreferenceResponse.setId(userNotificationPreference.getId());
                    NotificationType notificationType = noticeTypeMap.get(userNotificationPreference.getNoticeTypeId());
                    userNoticePreferenceResponse.setNoticeTypeName(notificationType.getNoticeTypeName());
                    userNoticePreferenceResponse.setNoticeTypeDesc(notificationType.getNoticeTypeDesc());
                    userNoticePreferenceResponse.setUserPreference(userNotificationPreference.getConfigNum());
                    return userNoticePreferenceResponse;
                })
                .toList();
        return userNoticePreferenceList;
    }

    @Override
    public Boolean updateUserNoticePreference(UserInfoData userInfoData, UserNoticeDto.UserNoticePreferenceUpdateRequest userNoticePreferenceUpdateRequest) {
        UserNotificationPreference userNotificationPreference = userNotificationPreferenceMapper.selectById(userNoticePreferenceUpdateRequest.getId());
        if (ObjectUtils.isEmpty(userNotificationPreference) || !userNotificationPreference.getUserId().equals(userInfoData.getId())) {
            throw new BusinessException(PARAMS_ERROR);
        }
        userNotificationPreference.setConfigNum(userNoticePreferenceUpdateRequest.getUserPreference());
        userNotificationPreferenceMapper.updateById(userNotificationPreference);
        return Boolean.TRUE;
    }

    @Override
    public PageResponse<UserNoticeDto.UserNoticeData> getUserNoticePage(UserInfoData userInfoData, UserNoticeDto.UserNoticePageRequest userNoticePageRequest) {
        PageResult<UserNotification> userNotificationPageResult = userNotificationMapper.pageUserNotice(userInfoData, userNoticePageRequest);
        List<UserNotification> contentData = userNotificationPageResult.getContentData();
        PageResponse<UserNoticeDto.UserNoticeData> userNoticeDataPageResponse = new PageResponse<>();
        if (ObjectUtils.isEmpty(contentData)) return userNoticeDataPageResponse;
        Set<Long> typeIds = contentData.stream().map(UserNotification::getNoticeTypeId).collect(Collectors.toSet());
        List<NotificationType> notificationTypeList = notificationTypeMapper.selectByIds(new ArrayList<>(typeIds));
        Map<Long, NotificationType> notificationTypeMap = notificationTypeList.stream()
                .collect(Collectors.toMap(NotificationType::getId, Function.identity()));
        userNoticeDataPageResponse.setValue(userNoticePageRequest.getPage()
                , userNotificationPageResult.getTotalSize()
                , UserNoticeConvert.toUserNoticeDataList(userNotificationPageResult.getContentData(), notificationTypeMap));
        return userNoticeDataPageResponse;
    }

    @Override
    public Boolean delUserNotice(UserInfoData userInfoData, UserNoticeDto.UserNoticeDelRequest userNoticeDelRequest) {
        userNotificationMapper.deleteByIds(userInfoData.getId(), userNoticeDelRequest.getIds());
        return Boolean.TRUE;
    }

    @Override
    public Boolean updateUserNoticeStatus(UserInfoData userInfoData, UserNoticeDto.UserNoticeStatusUpdateRequest userNoticeStatusUpdateRequest) {
        userNotificationMapper.updateUserNoticeStatus(userInfoData.getId(), userNoticeStatusUpdateRequest.getIds(), UserNoticeStatus.READ.getCode());
        return Boolean.TRUE;
    }

    @Async("userDefaultTaskExecutor")
    @Override
    public void initUserNoticePreference(String username) {
        log.info("初始化用户通知配置:{}", username);
        if (StringUtils.isEmpty(username)) {
            log.error("用户名不能为空，初始化通知配置失败");
            return;
        }

        List<NotificationType> notificationTypeList = notificationTypeMapper.selectAllValid();
        User user = userMapper.selectUserByUserName(username);
        if (ObjectUtils.isEmpty(user)) {
            log.error("用户不存在，初始化通知配置失败");
            return;
        }
        for (NotificationType notificationType : notificationTypeList) {
            UserNotificationPreference userNotificationPreference = new UserNotificationPreference();
            userNotificationPreference.setUserId(user.getId());
            userNotificationPreference.setNoticeTypeId(notificationType.getId());
            userNotificationPreferenceMapper.save(userNotificationPreference);
        }
    }
}
